package top.hmtools.manager.asynchronous;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import top.hmtools.RLContext;
import top.hmtools.base.StringTools;
import top.hmtools.pojo.RequestLogBean;

/**
 * 基于线程池将追加的用户请求扩展日志信息缓存队列数据写入数据库的 <br>
 * 具体执行写入工作的线程代码块
 * @author HyboJ
 *
 */
public class ThreadWorkerExtra implements Runnable{
	
protected final Logger logger = LoggerFactory.getLogger(ThreadWorkerExtra.class);
	
	private RLContext rlContext;

	public ThreadWorkerExtra(RLContext rlContext) {
		this.rlContext = rlContext;
	}

	@Override
	public void run() {
		int dataCount = 0;//计划写入数据库总条数
		int successCount = 0;//成功写入数据库总条数
		int failCount = 0;//失败写入数据库总条数
		int currSizeOfQueue = 0;//获取队列中的数据条数
		List<RequestLogBean> beansToDB = null;//准备写入数据库的日志记录信息集合
		int batchItemSize = this.rlContext.requestLoggerAutoConfiguration.getBatchItemSize();//单批次写入数据库的最大条目数
		
		//当当前缓存中日志信息数量大于单批次写入数据库的最大数据条数时，执行写入操作
		while((currSizeOfQueue = this.rlContext.requestLogBeanExtraQueue.getQueueSize()) >= batchItemSize){
			dataCount = dataCount + batchItemSize;
			try {
				//批量写入数据库的 用户请求日志数据集合
				beansToDB = new ArrayList<RequestLogBean>();
				
				//准备数据
				for (int ii = 0; ii < batchItemSize; ii++) {
					RequestLogBean pollOfQueue = this.rlContext.requestLogBeanExtraQueue.poll();
					//在写入数据库前，对数据进行最后一次验证
					if(pollOfQueue == null || StringTools.isBlank(pollOfQueue.getRequestID())){
						continue;
					}
					beansToDB.add(pollOfQueue);
				}
				if(beansToDB==null || beansToDB.size()<1){
					continue;
				}
				
				//执行写入到数据库
				int addLogsCount = 0;
				addLogsCount = this.rlContext.requestLoggerService.addLogsExtraInfos(beansToDB);
				successCount = successCount + addLogsCount;
				logger.debug("计划写入数据库的追加的埋点用户访问日志扩展数据，共计" + beansToDB.size()	+ "条：");
				logger.debug(JSON.toJSONString(beansToDB));
				logger.debug("成功写入数据库记录数为：" + addLogsCount);
			} catch (Exception e) {
				logger.error(e.getMessage(),e);
				if(beansToDB!=null){
					logger.debug("计划写入数据库的追加的埋点用户访问日志扩展数据，失败：" + beansToDB.size()	+ "条：");
					logger.debug(JSON.toJSONString(beansToDB));
				}
				
				//尝试补救写入数据库（一条条写入）
				if(beansToDB!=null && beansToDB.size()>0){
					logger.debug("将失败的数据尝试补救写入数据库（一条条写入）");
					int tryAgainSuccessCount = 0;
					for(RequestLogBean item:beansToDB){
						try {
							int addLogs = this.rlContext.requestLoggerService.addLogsExtraInfos(item);
							tryAgainSuccessCount = tryAgainSuccessCount + addLogs;
						} catch (Exception e2) {
							continue;
						}
					}
					logger.debug("补救成功写入数据库"+tryAgainSuccessCount+"条");
					successCount=successCount+tryAgainSuccessCount;
				}
			}
			failCount = dataCount - successCount;
			if(logger.isDebugEnabled()){
				logger.debug("线程名为："+Thread.currentThread().getName()+"执行写入追加的用户访问请求日志扩展信息缓存队列数据到数据库执行完成。");
				logger.debug("计划写入数据库的数据总条数为："+dataCount);
				logger.debug("成功写入数据库的数据总条数为："+successCount);
				logger.debug("失败写入数据库的数据总条数为："+failCount);
			}
		}
	}

}
